using System;
using System.Collections.Generic;
using System.Text;

namespace IUPUI.StellarResults
    {
    /// <summary>
    /// Represents the offset (x,y) of an <see cref="AstronomicalObject"/> from a center point.
    /// </summary>
    public class ViewOffset
        {
        #region Private Properties
        int m_X = 0;
        int m_Y = 0;
        private bool m_Visible = false;
        #endregion Private Properties

        #region Public Properties
        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="ViewOffset"/> is visible.
        /// </summary>
        /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
        public bool Visible
            {
            get
                {
                return m_Visible;
                }
            set
                {
                m_Visible = value;
                }
            }

        /// <summary>
        /// Gets the X.
        /// </summary>
        /// <value>The X.</value>
        public int X
            {
            get
                {
                return m_X;
                }
            }

        /// <summary>
        /// Gets the Y.
        /// </summary>
        /// <value>The Y.</value>
        public int Y
            {
            get
                {
                return m_Y;
                }
            }
        #endregion Public Properties

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="ViewOffset"/> class.
        /// </summary>
        public ViewOffset()
            {
            }
        #endregion Constructors

        #region Public Methods
        /// <summary>
        /// Computes the offset (x,y) of the <see cref="AstronomicalObject"/> from a center point.
        /// </summary>
        /// <param name="objectAltazimuth">The <see cref="Altazimuth"/> of the stellar object.</param>
        /// <param name="observatory">The observatory.</param>
        /// <param name="viewWidth">The width (in pixels) of the view screen for the observatory.</param>
        public void ComputeOffset(
            Altazimuth objectAltazimuth,
            Observatory observatory,
            int viewWidth)
            {
            ComputeOffset(
                objectAltazimuth,
                observatory.Altazimuth,
                (double)observatory.ViewAngle,
                viewWidth);
            }

        /// <summary>
        /// Computes the offset (x,y) of the <see cref="AstronomicalObject"/> from a center point.
        /// </summary>
        /// <param name="objectAltazimuth">The <see cref="Altazimuth"/> of the stellar object.</param> 
        /// <param name="observatoryAltazimuth">The <see cref="Altazimuth"/> of the observatory.</param> 
        /// <param name="viewAngle">The view angle of the observatory.</param> 
        /// <param name="viewWidth">The width (in pixels) of the view screen for the observatory.</param>
        public void ComputeOffset(
            Altazimuth objectAltazimuth,
            Altazimuth observatoryAltazimuth,
            double viewAngle,
            int viewWidth)
            {
            int signAz = 1;
            int signAlt = 1;

            double deltaAlt = 0;
            double deltaAz = 0;
            double objectAz = objectAltazimuth.Azimuth;
            double observeAz = observatoryAltazimuth.Azimuth;

            // altitude differences
            if (objectAltazimuth.Altitude < observatoryAltazimuth.Altitude)
                {
                // object is below telescope, delta < 0
                signAlt = -1;
                }

            // azimuth differences
            if (observeAz > 180)
                {
                if ((objectAz < observeAz) & (objectAz > observeAz - 180))
                    {
                    signAz = -1;
                    }
                }
            else
                {
                if (((objectAz >= observeAz) & (objectAz <= observeAz + 180)) == false)
                    {
                    signAz = -1;
                    }
                }
            // get deltas
            AstronomicalCalculations.ComputeDeltas(observatoryAltazimuth.Altitude,
                        observeAz,
                        objectAltazimuth.Altitude,
                        objectAz,
                        viewAngle,
                        out deltaAlt,
                        out deltaAz,
                        out m_Visible);

            if (Math.Sin(viewAngle * Math.PI / 180) == 0)
                {
                //this occurs IIF ViewAngle = 360, Assert in test 0<ViewAngle<90
                m_X = 0;
                m_Y = 0;
                }
            else
                {
                m_X = (int)(signAz * viewWidth / 2 * Math.Sin(deltaAz * Math.PI / 180) / Math.Sin(viewAngle * Math.PI / 180));
                m_Y = (int)(signAlt * viewWidth / 2 * Math.Sin(deltaAlt * Math.PI / 180) / Math.Sin(viewAngle * Math.PI / 180));
                }


            }



        #endregion Public Methods
        }
    }
